package com.dm.cloud.images.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.model.Container;
import com.dm.cloud.images.common.mode.ImagesAppArrangeExtend;
import com.dm.cloud.images.common.po.ImagesAppTask;
import com.dm.cloud.images.common.po.ImagesContainer;
import com.dm.cloud.images.common.po.ImagesEndpoint;
import com.dm.cloud.images.mode.AppArrangeModel;
import com.dm.cloud.images.mode.AppContainerModel;
import com.dm.cloud.images.mode.AppInfoModel;
import com.dm.cloud.images.mode.AppNodeInfoModel;
import com.dm.cloud.images.service.ImagesAppTaskService;
import com.dm.cloud.images.service.ImagesContainerService;
import com.dm.cloud.images.service.ImagesEndpointService;
import com.dm.cloud.images.util.DockerUtil;
import com.dm.cloud.tkmybatis.service.BaseMapper;
import com.dm.cloud.images.mapper.ImagesAppArrangeMapper;
import com.dm.cloud.images.service.ImagesAppArrangeService;
import com.dm.cloud.images.common.po.ImagesAppArrange;
import com.dm.cloud.core.exception.CustomException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
   * @author hcx
   * @type ImagesAppArrangeServiceImpl.java
   * @desc ImagesAppArrange serviceImpl
   */
@Service

@Transactional

public class ImagesAppArrangeServiceImpl implements ImagesAppArrangeService {


    @Autowired
    private ImagesAppArrangeMapper imagesAppArrangeMapper;

    @Autowired
    private ImagesContainerService imagesContainerService;

    @Autowired
    private ImagesEndpointService imagesEndpointService;

    @Autowired
    private ImagesAppTaskService imagesAppTaskService;

    @Override
    public BaseMapper getMapper() {
        return imagesAppArrangeMapper;
    }
    public void processBeforeOperation(ImagesAppArrange entity, BaseOperationEnum operationEnum) throws CustomException {
    }

    public void processAfterOperation(ImagesAppArrange entity, BaseOperationEnum operationEnum) throws CustomException {
    }

    @Override
    public boolean deleteByNodeIdAndImagesId(String containerId, String nodeId) {
        int x=imagesAppArrangeMapper.deleteByNodeIdAndImagesId(containerId,nodeId);
        return x>0?true:false;
    }

    @Override
    public AppInfoModel appInfo(String appCode) {
        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("应用Code不能为空!");
        }
        AppInfoModel appinfo=new AppInfoModel();

        List<ImagesEndpoint> appNodes = imagesEndpointService.findByAppCode(appCode);
        if(appNodes==null || appNodes.isEmpty()){
            return appinfo;
        }
        appinfo.setNodeSize(appNodes.size());// 设置节点总数

        Map<String,AppNodeInfoModel> nodeInfoMaps=new LinkedHashMap<>();//用于统计单节点状态
        Map<String,ImagesEndpoint> nodeMaps=new HashMap<>();
        for (ImagesEndpoint appNode : appNodes) {
            nodeMaps.put(appNode.getId(),appNode);
            AppNodeInfoModel nodeInfo=new AppNodeInfoModel();
            nodeInfo.setNodeName(appNode.getName());
            nodeInfo.setNodeId(appNode.getId());
            nodeInfo.setContainerSize(0);
            nodeInfo.setNodeAddress(appNode.getHost());
            if(appNode.getState()==1){
                appinfo.addActivateNodeSize(1); //可用节点
                nodeInfo.setNodeStatus(1);
            }else{
                appinfo.addErrNodeSize(1);  //异常节点
                nodeInfo.setNodeStatus(1);
            }
            nodeInfoMaps.put(appNode.getId(),nodeInfo);
        }
        List<ImagesContainer> containers= imagesContainerService.findByAppCode(appCode);
        if(containers==null || containers.isEmpty()){
            return appinfo;
        }
        appinfo.setContainerSize(containers.size()); //设置应用容器总量
        for (ImagesContainer container : containers) {
            ImagesEndpoint endpoint = nodeMaps.get(container.getNodeId());
            AppNodeInfoModel nodeInfo = nodeInfoMaps.get(container.getNodeId());
            nodeInfo.addContainerSize(1); //添加一个总量
            DockerClient client =null;
            try {
                client = DockerUtil.get(endpoint.getHost(), endpoint.getDockerPort());
                Container containerInfo = DockerUtil.containerDetail(client, container.getContainerId());
                String status = containerInfo.getState().toLowerCase();
                appinfo.addStatus(status,1); //设置应用容器状态的数量
                //设置节点的状态统计
                nodeInfo.addStatus(status,1);
                AppNodeInfoModel.ContainerInfo nodeContainerInfo =AppNodeInfoModel.ContainerInfo
                        .builder()
                        .id(containerInfo.getId())
                        .image(containerInfo.getImage())
                        .names(containerInfo.getNames())
                        .status(status)
                        .command(containerInfo.getCommand())
                        .build();
                nodeInfo.addContainerInfo(nodeContainerInfo); //添加节点种容器基本信息
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                try {
                    client.close();
                }catch (Exception e){}
            }
        }
        appinfo.setNodeInfos(new ArrayList<>(nodeInfoMaps.values()));
        return appinfo;
    }

    @Override
    @Transactional
    public AppArrangeModel arrange(AppArrangeModel arrangeModel) {
        if(StrUtil.isEmpty(arrangeModel.getAppCode())){
            throw new CustomException("请指定应用");
        }
        if(ArrayUtil.isEmpty(arrangeModel.getArranges())){
            throw new CustomException("编排信息不能为空");
        }
        imagesAppArrangeMapper.deleteByAppCode(arrangeModel.getAppCode()); //清理应用相关的编排信息
        List<List<AppArrangeModel.AppArrangeItem>> arrangeList = arrangeModel.getArranges();
        for (int i = 0; i < arrangeList.size(); i++) {
            int step=i;
            List<AppArrangeModel.AppArrangeItem> appArrangeItems=arrangeList.get(i);
            for (int i1 = 0; i1 < appArrangeItems.size(); i1++) {
                int stepIndex=i1;
                AppArrangeModel.AppArrangeItem appArrangeItem = appArrangeItems.get(i1);
                ImagesAppArrange arrange=ImagesAppArrange
                        .builder()
                        .stepIndex(stepIndex)
                        .appCode(arrangeModel.getAppCode())
                        .step(step)
                        .containerId(appArrangeItem.getContainerId())
                        .nodeId(appArrangeItem.getNodeId())
                        .timeout(appArrangeItem.getTimeout()==null || appArrangeItem.getTimeout()<=0?120:appArrangeItem.getTimeout())
                        .successCondition(appArrangeItem.getSuccessCondition())
                        .build();
                if(insert(arrange)>0){
                    appArrangeItem.setId(appArrangeItem.getId()); //存储成功后设置ID
                }else{
                    throw new CustomException("插入失败!"+appArrangeItem.getContainerId());
                }
            }
        }
        return arrangeModel;
    }

    @Override
    public AppArrangeModel getArrange(String appCode) {
        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("请指定应用");
        }
        AppArrangeModel appArrangeModel=new AppArrangeModel();
        List<ImagesAppArrange> arrangesList = imagesAppArrangeMapper.findByAppCode(appCode);
        List<List<AppArrangeModel.AppArrangeItem>> arranges=new ArrayList<>();
        for (int i = 0; i < arrangesList.size(); i++) {
            ImagesAppArrange arrange = arrangesList.get(i);
            List<AppArrangeModel.AppArrangeItem> stepItems=new ArrayList<>();
            if(arranges.size()>arrange.getStep()){
                //有子级列表
                stepItems = arranges.get(arrange.getStep());
            }else {
                //没有子级列表
                stepItems=new ArrayList<>();
                arranges.add(stepItems);
            }
            AppArrangeModel.AppArrangeItem stepItem=new AppArrangeModel.AppArrangeItem();
            stepItem.setContainerId(arrange.getContainerId());
            stepItem.setTimeout(arrange.getTimeout());
            stepItem.setNodeId(arrange.getNodeId());
            stepItem.setSuccessCondition(arrange.getSuccessCondition());
            stepItem.setId(arrange.getId());
            stepItems.add(stepItem);
        }
        appArrangeModel.setAppCode(appCode);
        appArrangeModel.setArranges(arranges);
        return appArrangeModel;
    }

    @Override
    public Boolean startApp(String appCode) {
        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("appCode不能为空!");
        }
        ImagesAppTask appTask=imagesAppTaskService.findByAppCode(appCode);
        if(appTask==null){
            appTask=ImagesAppTask
                    .builder()
                    .appCode(appCode)
                    .status(0)
                    .tp(1)
                    .serviceId(null)
                    .build();
            imagesAppTaskService.insert(appTask);
        }else{
            if(appTask.getStatus()==2){//上一轮执行完成后才能创建任务
                //上次的任务已经完成的状态，那么重置
                appTask.setStatus(0);
                appTask.setTp(1);
                appTask.setServiceId(null);
                imagesAppTaskService.updateTaskParamById(0,1,null,appTask.getId());
                //此处应该清除启动历史记录
            }else{
                //状态(status)为0 1 的表示正在执行
                //tp: 1启动应用任务  2关闭应用任务
                if(appTask.getTp()==2){
                    throw new CustomException("上一轮关闭应用操作还未完成!");
                }
            }
        }
        //操作完成，等待定时任务
        return true;
    }

    @Override
    public Boolean stopApp(String appCode) {
        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("appCode不能为空!");
        }
        ImagesAppTask appTask=imagesAppTaskService.findByAppCode(appCode);
        if(appTask==null){
            appTask=ImagesAppTask
                    .builder()
                    .appCode(appCode)
                    .status(0)
                    .tp(2)
                    .serviceId(null)
                    .build();
            imagesAppTaskService.insert(appTask);
        }else{
            if(appTask.getStatus()==2){ //上一轮执行完成后才能创建任务
                //上次的任务已经完成的状态，那么重置
                appTask.setStatus(0);
                appTask.setTp(2);
                appTask.setServiceId(null);
                imagesAppTaskService.updateTaskParamById(0,2,null,appTask.getId());
                //此处应该清除启动历史记录
            }else{
                //状态(status)为0 1 的表示正在执行
                //tp: 1启动应用任务  2关闭应用任务
                if(appTask.getTp()==1){
                    throw new CustomException("上一轮启动应用操作还未完成!");
                }
            }
        }
        //操作完成，等待定时任务
        return true;
    }

    @Override
    public List<ImagesAppArrange> findByAppCode(String appCode) {
        return imagesAppArrangeMapper.findByAppCode(appCode);
    }

    @Override
    public Boolean restartApp(String appCode) {
        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("appCode不能为空!");
        }
        ImagesAppTask appTask=imagesAppTaskService.findByAppCode(appCode);
        if(appTask==null){
            appTask=ImagesAppTask
                    .builder()
                    .appCode(appCode)
                    .status(0)
                    .tp(3)
                    .serviceId(null)
                    .build();
            imagesAppTaskService.insert(appTask);
        }else{
            if(appTask.getStatus()==2){//上一轮执行完成后才能创建任务
                //上次的任务已经完成的状态，那么重置
                appTask.setStatus(0);
                appTask.setTp(3);
                appTask.setServiceId(null);
                imagesAppTaskService.updateTaskParamById(0,3,null,appTask.getId());
                //此处应该清除启动历史记录
            }else{
                //状态(status)为0 1 的表示正在执行
                //tp: 1启动应用任务  2关闭应用任务
                if(appTask.getTp()==2){
                    throw new CustomException("上一轮关闭应用操作还未完成!");
                }
            }
        }
        //操作完成，等待定时任务
        return true;
    }

    @Override
    public AppContainerModel containerStatus(String appCode) {

        if(StrUtil.isEmpty(appCode)){
            throw new CustomException("appCode不能为空!");
        }
        AppContainerModel appContainerModel=new AppContainerModel();
        appContainerModel.setCode(appCode);

        ImagesAppTask appTask = imagesAppTaskService.findByAppCode(appCode);
        if(appTask!=null){
            Integer appStatus = appTask.getStatus();
            Integer appTp=appTask.getTp();
            int appOptionStatus=0;
            if(appStatus==1 && appTp==1){
                appOptionStatus=1;
            }else if(appStatus==1 && appTp==2){
                appOptionStatus=2;
            }else if(appStatus==1 && appTp==3){
                appOptionStatus=3;
            }
            appContainerModel.setAppOptionStatus(appOptionStatus);
        }else{
            appContainerModel.setAppOptionStatus(0);
        }
        List<ImagesEndpoint> appNodes = imagesEndpointService.findByAppCode(appCode);
        if(appNodes==null || appNodes.isEmpty()){
            return appContainerModel;
        }
        Map<String,ImagesEndpoint> nodeMaps=new HashMap<>();
        for (ImagesEndpoint appNode : appNodes) {
            nodeMaps.put(appNode.getId(),appNode);
        }
        //编排以及关联信息
        List<ImagesAppArrangeExtend> imagesAppArrangeExtends=imagesAppArrangeMapper.findAppStatus(appCode);
        if(imagesAppArrangeExtends!=null && !imagesAppArrangeExtends.isEmpty()){
            List<List<AppContainerModel.ContainerModel>> containers=new ArrayList<>();
            for (ImagesAppArrangeExtend imagesAppArrangeExtend : imagesAppArrangeExtends) {
                List<AppContainerModel.ContainerModel> containerModels=null;
                if(imagesAppArrangeExtend.getStep()>=containers.size()){
                    containerModels=new ArrayList<>();
                    containers.add(containerModels);
                }else{
                    containerModels=containers.get(imagesAppArrangeExtend.getStep());
                }
                AppContainerModel.ContainerModel containerModel=new AppContainerModel.ContainerModel();
                containerModel.setContainerId(imagesAppArrangeExtend.getContainerId());
                containerModel.setContainerResult(imagesAppArrangeExtend.getContainerResult());
                containerModel.setId(imagesAppArrangeExtend.getId());
                containerModel.setOperateStatus(imagesAppArrangeExtend.getOperateStatus());
                containerModel.setNodeId(imagesAppArrangeExtend.getNodeId());
                containerModel.setErrStr(imagesAppArrangeExtend.getErrStr());
                DockerClient client=null;
                try {
                    //获取容器详情
                    client = imagesEndpointService.getClientByNodeId(imagesAppArrangeExtend.getNodeId());
                    Container detail = DockerUtil.containerDetail(client, imagesAppArrangeExtend.getContainerId());
                    containerModel.setNames(Arrays.asList(detail.getNames()));
                    containerModel.setRunningState(detail.getState());
                }catch (Exception e){
                    e.printStackTrace();
                    containerModel.setNames(Arrays.asList("容器连接异常"));
                    containerModel.setRunningState("error");
                }finally {
                    try {
                        client.close();
                    }catch (Exception e){}
                }
                containerModels.add(containerModel);
            }
            appContainerModel.setContainers(containers);
        }
        return appContainerModel;
    }

}
